import datetime
import math

import common
import utils
import warningExtractor
import stormReportExtractor
import radarExtractor
import radarAnalysis

def automatedShearStatGenerator():
	print 'loading warnings...'
	warnings = warningExtractor.loadTorWarnings([2010])
	print 'loading reports...'
	reports = stormReportExtractor.loadStormReports([2010])

	output = False
	
	if output:
		foutShearStats = open('shear-stats.arff', 'w')
		
		foutShearStats.write('@RELATION sheardata\n\n'\
							'@ATTRIBUTE avgRef NUMERIC\n'\
							'@ATTRIBUTE avgVelDiff NUMERIC\n'\
							'@ATTRIBUTE countyDist NUMERIC\n'\
							'@ATTRIBUTE radarDist NUMERIC\n'\
							'@ATTRIBUTE correct {0,1}\n\n'\
							'@DATA\n')
	
	total = 0
	withShearFeatures = 0

	numShearFeatures = {}
	
	for warn in warnings:
		print '\nwarning for %s, %s'%(warn["countyName"], str(warn["iTime"]))
		
		# find x/y coords of warning lat/lon
		countyLatLon = warn["countyLatLon"]
		countyXYCoords = utils.latLonToXY(countyLatLon[0], countyLatLon[1])
				
		# if the warning is very far from the radar, skip it
		if utils.latLonDist(countyLatLon, common.KTLXLocation) > 90:
			print 'storm too far from radar'
			continue

		# find the radar image that is closest in time to the warning time
		stormRel0 = radarExtractor.getClosestRadarData(warn["iTime"], num = 0, product='stormRel0')
		stormRel1 = radarExtractor.getClosestRadarData(warn["iTime"], num = 0, product='stormRel1')
		stormRel2 = radarExtractor.getClosestRadarData(warn["iTime"], num = 0, product='stormRel2')
		stormRel3 = radarExtractor.getClosestRadarData(warn["iTime"], num = 0, product='stormRel3')
		baseRef = radarExtractor.getClosestRadarData(warn["iTime"], num = 0, product='baseRef0')

		# convert the chosen radar files to NetCDF
		stormRel0Nc = radarExtractor.radarToNetCDF(stormRel0)
		stormRel1Nc = radarExtractor.radarToNetCDF(stormRel1)
		stormRel2Nc = radarExtractor.radarToNetCDF(stormRel2)
		stormRel3Nc = radarExtractor.radarToNetCDF(stormRel3)
		baseRefNc = radarExtractor.radarToNetCDF(baseRef)

		if len(stormRel0Nc) == 0 or len(stormRel1Nc) == 0 or \
		   len(stormRel2Nc) == 0 or len(stormRel3Nc) == 0 or len(baseRefNc) == 0: 
			continue

		# extract the radar data from the NetCDF files
		baseRefData, baseRefPrefix = radarExtractor.getRadarData(baseRefNc[0], flat = False, flip = True)
		stormRel0Data, stormRel0Prefix = radarExtractor.getRadarData(stormRel0Nc[0], flat = False, flip = True)
		stormRel1Data, stormRel1Prefix = radarExtractor.getRadarData(stormRel1Nc[0], flat = False, flip = True)
		stormRel2Data, stormRel2Prefix = radarExtractor.getRadarData(stormRel2Nc[0], flat = False, flip = True)
		stormRel3Data, stormRel3Prefix = radarExtractor.getRadarData(stormRel3Nc[0], flat = False, flip = True)

		print 'finding velocity couplets...'
		shearFeatures = radarAnalysis.findShearFeatures({'stormRel0':stormRel0Data, 'stormRel1':stormRel1Data, 
										   'stormRel2':stormRel2Data, 'stormRel3':stormRel3Data}, 
										   baseRefData, targetLatLon = countyLatLon, maxDist = 45, verbose=True)

		print 'found %d shear features'%len(shearFeatures)
		total += 1
		if len(shearFeatures) > 0:
			withShearFeatures += 1
		
		if len(shearFeatures) in numShearFeatures.keys():
			numShearFeatures[len(shearFeatures)] += 1
		else:
			numShearFeatures[len(shearFeatures)] = 1
		#print 'printing %d shear features...'%len(shearFeatures)
		#for feature in shearFeatures:
		#	print 'feature: %s, ref = %f, velDiff = %f, score = %f'%(str(feature.center), feature.avgRef, feature.avgVelDiff, feature.score)
	
	print 'total = %d, withShearFeatures = %d, percent = %f'%(total, withShearFeatures, float(withShearFeatures)/total)
	for k in numShearFeatures.keys():
		print '%d features: %d'%(k, numShearFeatures[k])
	
	if output:
		foutShearStats.close()
	


def warnStats():	
	print 'loading warnings...'
	warnings = loadTorWarnings([2010])
	print 'loading reports...'
	reports = loadStormReports([2010])

	# sort by time
	warnings.sort(key = lambda x:x['iTime'])

	startingCount = 1
	count = 1
	# open the file, if it exists, and find the number of the last recorded warning
	if os.path.exists('couplet-stats.txt'):
		fStats = open('couplet-stats.txt', 'r')
		# find the ending count
		for line in fStats:
			lineParts = line.split('--')
			if len(lineParts) > 1:
				startingCount = int(lineParts[0])

	# open the file again, for appending
	fStats = open('couplet-stats.txt', 'a')

	writeNewWarning = True
	print 'searching warnings...'
	for warn in warnings:
		reps = matchStormWithWarning(warn, reports)

		# find x/y coords of warning lat/lon
		coords = warn["countyLatLon"]
		xyCoords = latLonToXY(coords[0], coords[1])
		#print 'xyCoords = %s'%str(xyCoords)
		
		# skip to the first un-recorded warning
		
		if count < startingCount:
			count += 1
			continue

		print '\nwarning for %s, %s'%(warn["countyName"], str(warn["iTime"]))
		if writeNewWarning:
			fStats.write('%d--%s\n'%(count, str(warn["iTime"])))
			fStats.flush()

		# print out reports associated with this warning
		print 'reports:'
		for rep in reps:
			print 'report at %s, starting at %s'%(rep["time"], (rep["slat"], rep["slon"]))
		print

		stormRel = getClosestRadarData(warn["iTime"], num = 0, product='stormRel0')
		baseRef = getClosestRadarData(warn["iTime"], num = 0, product='baseRef0')

		stormRelNc = radarToNetCDF(stormRel)
		baseRefNc = radarToNetCDF(baseRef)

		stormRelData, stormRelPrefix = getRadarData(stormRelNc[0], flat = False, flip = True)
		radarToImg(stormRelData, stormRelPrefix, stormRelNc[0].split('.')[0], verbose = False, mark = xyCoords)

		baseRefData, baseRefPrefix = getRadarData(baseRefNc[0], flat = False, flip = True)
		radarToImg(baseRefData, baseRefPrefix, baseRefNc[0].split('.')[0], verbose = False, mark = xyCoords)

		print 'finding velocity couplets...'
		vorts = findVortCouplets(stormRelData, baseRefData, targetLatLon = coords, maxDist = 50)

		# regions of the image that have been marked -- tuples of (x1, y1, x2, y2)
		completeAreas = []

		k = 0
		while k < len(vorts):

			# check if this vort is in an area that has been marked as complete
			complete = False
			curCoords = (vorts[k][0], vorts[k][1])
			for area in completeAreas:
				if curCoords[0] >= area[0] and curCoords[0] <= area[2] and \
				   curCoords[1] >= area[1] and curCoords[1] <= area[3]:
					complete = True
					break
			if complete:
				k += 1
				continue
			else:
				completeAreas.append((curCoords[0]-2, curCoords[1]-2, curCoords[0]+2, curCoords[1]+2))

			print 'maxVel1pxDiff = %f\tmaxVel2pxDiff = %f\n' \
				  'avgVel1px = %f\t\tavgVel2px = %f\n' \
				  'avgVel1pxDiff = %f\tavgVel2pxDiff = %f\n' \
				  'varVel1px = %f\t\tvarVel2px = %f\n' \
				  'avgRef1px = %f\t\tavgRef2px = %f\n' \
				  'ratioToFromRadar1px = %f\tratioToFromRadar2px = %f\n' \
				  'dist = %f\t\tscore = %f'%(round(vorts[k][2],2), round(vorts[k][3], 2),
											round(vorts[k][4], 2), round(vorts[k][5], 2),
											round(vorts[k][6], 2), round(vorts[k][7], 2),
											round(vorts[k][8], 2), round(vorts[k][9], 2),
											round(vorts[k][10], 2), round(vorts[k][11], 2),
											round(vorts[k][12], 2), round(vorts[k][13], 2),
											round(vorts[k][15], 2), vorts[k][16])
			print
			print vorts[k][14]

			radarToImg(stormRelData, stormRelPrefix, "%s-vort-%d"%(stormRelNc[0].split('.')[0], k),
							   center = curCoords, dim = (50, 50), verbose = False, mark = (-1, -1), markLen = 0)
			radarToImg(baseRefData, baseRefPrefix, "%s-vort-%d"%(baseRefNc[0].split('.')[0], k),
							   center = curCoords, dim = (50, 50), verbose = False, mark = (-1, -1), markLen = 0)

			images = []
			images.append(('%s.bmp'%baseRefNc[0].split('.')[0]).replace('/', '\\'))
			images.append(("%s-vort-%d.bmp"%(stormRelNc[0].split('.')[0].replace('/', '\\'), k)))
			images.append(("%s-vort-%d.bmp"%(baseRefNc[0].split('.')[0].replace('/', '\\'), k)))

			# start the image viewer
			path = "C:/Program Files (x86)/IrfanView/i_view32.exe"
			si = subprocess.STARTUPINFO()
			si.dwFlags = subprocess.STARTF_USESHOWWINDOW
			si.wShowWindow = 1      # make the new window be in focus
			processes = []
			for i in images:
				processes.append(subprocess.Popen([path, i], startupinfo = si))

			# wait...
			action = raw_input("'y' for correct, 'n' to mark wrong and go to the next cuplet, "\
								"'s' to skip this couplet, 'b' to go back, 'q' for new storm, "\
								"'rv3' to generate grlevel3 data, or 'quit' to stop: ")

			# close all the open image viewer windows
			for p in processes:
				try:
					p.kill()
				except OSError:
					pass

			# mark that we should write the next warning to the file
			writeNewWarning = True

			if action == 'y':
				# mark the current couplet as correct, go to next couplet
				fStats.write('%s:1\n'%str(vorts[k]))
				fStats.flush()
				continue
			elif action == 'q':
				# skip to the next warning, don't write anything
				break
			elif action == 'n':
				# mark current couplet as wrong, go to next couplet
				fStats.write('%s:0\n'%str(vorts[k]))
				fStats.flush()
				k += 1
				continue
			elif action == 's':
				# skip the couplet without marking it as right or wrong
				k += 1
				continue
			elif action == 'b':
				# go back to the last couplet
				completeAreas.pop()
				k -= 1
				continue
			elif action == 'quit':
				# save the file and quit
				fStats.close()
				return
			elif action == 'rv3':
				# convert the folder to RV3
				warnTime = warn['iTime']
				radarFolder = '%s/%d/KTLX%d%.2d%.2d'%(RadarBaseDir, warnTime.year,
													 warnTime.year, warnTime.month, warnTime.day)

				# do not re-write the warning to the file (it's already there)
				writeNewWarning = False
				radarToRv3([radarFolder])
				continue
		count += 1
	fStats.close()


def loadObservedVortData():
	warningList = []
	fVortCoords = open("%s/warning-list.txt"%BaseDir, 'r')
	for line in fVortCoords:
		if line.strip() == "": continue
		lineParts = line.split(";")
		if len(lineParts) != 4: continue
		if lineParts[3].strip() == "": continue
		
		coords = lineParts[3].strip()
		coords = coords.rstrip(')')
		coords = coords.lstrip('(')
		coords = coords.split(',')
		coords = (int(coords[0].strip()), distToY(int(coords[1].strip())))
		
		countyName = lineParts[0].strip()
		warningTime = lineParts[1].strip()
		
		warningList.append({"countyName":countyName,
							"iTime":warningTime,
							"xyCoords":coords})
	return warningList
